/*
 * $Id$
 */
package ua.org.energy.vkek.site.web;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import ua.org.energy.vkek.site.model.AbstractEntity;
import ua.org.energy.vkek.site.model.Article;
import ua.org.energy.vkek.site.model.ArticleCategory;
import ua.org.energy.vkek.site.model.ArticleTag;
import ua.org.energy.vkek.site.server.*;

public class SiteControllerServlet extends BaseJsonServlet {

    @Override
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        RequestDispatcher disp;

        response.setContentType("text/html; charset=UTF-8");

        if (parseRequestAndFillHier(request.getPathInfo(), request)) {
            disp = getServletContext().getRequestDispatcher("/page.jsp");
            disp.include(request, response);
        } else {
            disp = getServletContext().getRequestDispatcher("/index.jsp");
            disp.forward(request, response);
        }

    }

    private boolean parseRequestAndFillHier(String extraPathInfo, HttpServletRequest request) throws DataIOException {
        ArticleCategory category = null;
        ArticleTag tag = null;
        Article article;

        if ((extraPathInfo != null) && (extraPathInfo.length() > 1)) { //если есть хоть какая-то информация после пути /s
            String[] pathParts = extraPathInfo.substring(1).split("/"); //начинать со второй позиции (без первого '/')
            if (pathParts.length > 0) {
                category = findHierObjects(new ArticleCategory(), pathParts[0]);
                   if (category != null) {
                           request.setAttribute(ArticleCategory.class.getName(), category);
                   } else {
                       return false; //категория не найдена (ни по ключу, ни по имени) 
                   }
            }
            if (pathParts.length > 1) {
                tag = findHierObjects(new ArticleTag(), pathParts[1]);
                if ((tag != null) && (tag.getCategory().equals(category))) { //для соблюдения иерархии (иначе будут все подряд теги без указанной категории
                    request.setAttribute(ArticleTag.class.getName(), tag);
                } else {
                    tag = null;
                }
            }
            if (pathParts.length > 2) {
                article = findHierObjects(new Article(), pathParts[2]);
                if ((article != null) && (article.getTag().equals(tag))) {  //для соблюдения иерархии
                    request.setAttribute(Article.class.getName(), article);
                }
            }
            return true;
        } else {
            return false;
        }
    }

    /**
     * пробует сконвертировать строку в Key, если не получается возвращает null
     *
     * @param mayBeKey
     * @return Key
     */
    private Key probeKey(String mayBeKey) {
        try {
            return KeyFactory.stringToKey(mayBeKey);
        } catch (IllegalArgumentException e) {
            return null;
        }
    }

    /**
     * заполняет или имя обекта (articleTitle,categoryName,tagName) или ключ (в
     * зависимости от результата probeKey
     *
     * @param entity сущность (ArtivlrCategory,ArticleTag,Article)
     * @param mayBeKeyMayBeName - может ключ а может имя сущности переданное как
     * часть запроса
     * @return заполненную сущность
     * @throws DataIOException
     */
    private <T extends AbstractEntity> T findHierObjects(T entity, String mayBeKeyMayBeName) throws DataIOException {
        Key key = probeKey(mayBeKeyMayBeName);
        if (key != null) {
            if (entity instanceof ArticleCategory) {
                entity = (T) EMF.getEM().find(ArticleCategory.class, key);
            } else if (entity instanceof ArticleTag) {
                entity = (T) EMF.getEM().find(ArticleTag.class, key);
            } else if (entity instanceof Article) {
                entity = (T) EMF.getEM().find(Article.class, key);
            } else {
                entity = null;
            }
        } else {
            if (entity instanceof ArticleCategory) {
                entity = (T) CategoryUtils.findCategory(mayBeKeyMayBeName, EMF.getEM());
            } else if (entity instanceof ArticleTag) {
                entity = (T) TagUtils.findArticleTag(mayBeKeyMayBeName, EMF.getEM());
            } else if (entity instanceof Article) {
                entity = (T) ArticleUtils.findArticle(mayBeKeyMayBeName, EMF.getEM());
            } else {
                entity = null;
            }
        }
        return entity;
    }
}
